package conf

import (
	"io"
	"crypto/hmac"
	"crypto/sha1"
	"time"
	"encoding/json"
	"hash"
	"encoding/base64"
	log "github.com/sirupsen/logrus"
)

type Oss struct {
	Host               string
	Cdn                string 
	Upload_dir         string
	Expire_time        int64
	AccessKeySecret    string
	AccessKeyId        string
	Callback           OssCallback
}

func NewOss(args ...interface{}) *Oss{

	oss := new(Oss)

	oss.Host             = "http://bilipay.oss-cn-shanghai.aliyuncs.com"
	oss.Cdn              = "bilipay.oss-cn-shanghai.aliyuncs.com"
	oss.Upload_dir       = "dev/news/images/"
	oss.Expire_time      = 120
	oss.AccessKeySecret  = "2JjdLIC6ekY2wO14YvI8YhaP1l609R"
	oss.AccessKeyId      = "LTAIJDCwRKErganC"


	// oss.CallbackBody     = "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}&mimeType=${mimeType}&imageInfo.height=${imageInfo.height}&imageInfo.width=${imageInfo.width}&imageInfo.format=${imageInfo.format}&my_var=${x:my_var}"
	oss.Callback.CallbackBody = "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"
	return oss
}

type OssConfig struct{
    Expiration string `json:"expiration"`
    Conditions [][]string `json:"conditions"`
} 

type OssPolicyToken struct{
    AccessKeyId string `json:"accessid"`
    Host        string `json:"host"`
    Expire      int64 `json:"expire"`
    Signature   string `json:"signature"`
    Policy      string `json:"policy"`
    Directory   string `json:"dir"`
    Callback    string `json:"callback"`
    Cdn         string `json:"cdn"`
}

type OssCallback struct{
    CallbackUrl      string `json:"callbackUrl"`
    CallbackBody     string `json:"callbackBody"`
    CallbackBodyType string `json:"callbackBodyType"`
}

func (this *Oss) GetGmtIso8601(expire_end int64) string {
	return time.Unix(expire_end, 0).Format("2006-01-02T15:04:05Z")
}

func (this *Oss) GetPolicyToken() (interface{}, error) {
	now := time.Now().Unix()
    expire_end := now + this.Expire_time
    var tokenExpire = this.GetGmtIso8601(expire_end)

    //create post policy json
    var config OssConfig
    config.Expiration = tokenExpire  
    var condition []string
    condition = append(condition, "starts-with")
    condition = append(condition, "$key")
    condition = append(condition, this.Upload_dir)
    config.Conditions = append(config.Conditions, condition)

    //calucate signature
    result,err:=json.Marshal(config)
    debyte := base64.StdEncoding.EncodeToString(result)
    h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(this.AccessKeySecret))
    io.WriteString(h, debyte)
    signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))

    //callback
	// var callbackParam OssCallback
	// callbackParam = this.Callback
    // callbackParam.CallbackUrl = callbackUrl
    // callbackParam.CallbackBody = "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"
    // callbackParam.CallbackBodyType = "application/x-www-form-urlencoded"
    callback_str, err:=json.Marshal(this.Callback)
    if err != nil {
		log.Errorf("Oss callback json err: %v", err)
		return nil, err
    }
    callbackBase64 := base64.StdEncoding.EncodeToString(callback_str)
    var policyToken OssPolicyToken
    policyToken.AccessKeyId = this.AccessKeyId
    policyToken.Host = this.Host
    policyToken.Expire = expire_end
    policyToken.Signature = string(signedStr)
    policyToken.Directory = this.Upload_dir
    policyToken.Policy = string(debyte)
    policyToken.Callback = string(callbackBase64)
    policyToken.Cdn = this.Cdn
    if err != nil {
		log.Errorf("Oss Json policyToken err: %v", err)
		return nil, err
	}
    return policyToken, nil
}
